package models

import (
	"context"
	"errors"
	"go-chain-api/global"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	"log"
	"math/big"
	"strconv"
)

type WatchAddressInfo struct {
	ChainName      string `bson:"chainName" json:"chainName"`
	ChainId        uint64 `bson:"chainId" json:"chainId"`
	BlockNumber    uint64 `bson:"blockNumber" json:"blockNumber"`
	TxHash         string `bson:"txHash" json:"txHash"`
	From           string `bson:"from" json:"from"`
	To             string `bson:"to" json:"to"`
	Token          string `bson:"token" json:"token"`
	Amount         string `bson:"amount" json:"amount"` // 假设Amount是字符串类型
	Verify         uint64 `bson:"verify" json:"verify"`
	CallBackURL    string `bson:"callBackUrl" json:"callBackUrl"`
	CallBackTime   uint64 `bson:"callBackTime" json:"callBackTime"`
	CallBackResult string `bson:"callBackResult" json:"callBackResult"`
	CallBackNumber uint64 `bson:"callBackNumber" json:"callBackNumber"`
}

// GetList 获取列表
func (wai WatchAddressInfo) GetList(chainName string, chainId uint, verify string, pageIndex uint, pageSize uint) (int64, []WatchAddressInfo, error) {
	client := global.DBEngine.Database(global.DbConfig.DbName).Collection("watch_address_info")

	// 查找
	filter := bson.D{{"chainName", chainName}, {"chainId", chainId}}
	if verify != "" {
		verifyInt, _ := strconv.ParseUint(verify, 10, 64)
		filter = bson.D{{"chainName", chainName}, {"chainId", chainId}, {"verify", verifyInt}}
	}
	findOptions := options.Find()
	findOptions.SetSort(bson.D{{"_id", -1}})
	findOptions.SetSkip(int64(pageIndex))
	findOptions.SetLimit(int64(pageSize))

	// 获取总数
	count, err := client.CountDocuments(context.TODO(), filter, nil)
	if err != nil {
		return 0, []WatchAddressInfo{}, err
	}

	find, err := client.Find(context.TODO(), filter, findOptions)
	if err != nil {
		return 0, []WatchAddressInfo{}, err
	}

	var watchAddressInfos []WatchAddressInfo
	err = find.All(context.TODO(), &watchAddressInfos)
	if err != nil {
		return 0, []WatchAddressInfo{}, err
	}

	return count, watchAddressInfos, nil
}

// UpdateVerify 修改验证状态
func (wai WatchAddressInfo) UpdateVerify(chainName string, chainId uint, from string, to string, token string, amount string) (string, error) {
	client := global.DBEngine.Database(global.DbConfig.DbName).Collection("watch_address_info")
	// 先获取token信息
	var tokenInfo TokenInfo
	tokenInfo.GetTokenInfoByAddress(token)
	var number big.Float
	if _, ok := number.SetString(amount); !ok {
		log.Println("UpdateVerify 字符串转换为数字失败")
		return "", errors.New("UpdateVerify 字符串转换为数字失败")
	}

	decimals := tokenInfo.Decimals
	if decimals == 0 {
		decimals = 18
	}
	// 创建一个big.Int来表示10^18
	powerOfTen := big.NewInt(1)
	powerOfTen.Exp(big.NewInt(10), big.NewInt(int64(decimals)), nil)
	// 将数字乘以10^18
	number.Mul(&number, new(big.Float).SetInt(powerOfTen))
	// 将结果转换回字符串
	resultStr := number.Text('f', 0)
	filter := bson.D{{"chainName", chainName}, {"chainId", chainId}, {"from", from}, {"to", to}, {"token", token}, {"amount", resultStr}, {"verify", 0}}
	update := bson.D{{"$set", bson.D{{"verify", 1}}}}
	//只更新一条并返回当前记录中的txHash
	var resultInfo WatchAddressInfo
	err := client.FindOne(context.TODO(), filter).Decode(&resultInfo)
	if err != nil {
		return "", errors.New("未查询到数据")
	}

	//根据_id更新
	_, err = client.UpdateOne(context.TODO(), bson.D{{"txHash", resultInfo.TxHash}}, update)
	if err != nil {
		return "", err
	}
	return resultInfo.TxHash, nil
}
